package com.zdkj.subway.stm.controller;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zdkj.admin.api.dto.UserInfo;
import com.zdkj.common.core.constant.CommonConstants;
import com.zdkj.common.core.util.R;
import com.zdkj.common.log.annotation.SysLog;
import com.zdkj.common.security.annotation.Inner;
import com.zdkj.common.security.util.SecurityUtils;
import com.zdkj.common.sequence.sequence.Sequence;
import com.zdkj.subway.stm.constant.StmConstans;
import com.zdkj.subway.stm.dto.in.SwStOperateLogDTO;
import com.zdkj.subway.stm.entity.SwStCycle;
import com.zdkj.subway.stm.entity.SwStCycleApply;
import com.zdkj.subway.stm.enums.CycleEnum;
import com.zdkj.subway.stm.fegin.SupportService;
import com.zdkj.subway.stm.fegin.SystemUserService;
import com.zdkj.subway.stm.handler.LogHandler;
import com.zdkj.subway.stm.service.SwStCycleApplyService;
import com.zdkj.subway.stm.service.SwStCycleService;
import com.zdkj.subway.stm.util.LocalDateConverter;
import com.zdkj.subway.stm.util.LocalDateTimeConverter;
import com.zdkj.subway.stm.util.SelMapUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;


/**
 * 调票申请表(车站)
 *
 * @author 陈博
 * @date 2020-01-17 13:56:15
 */
@RestController
@AllArgsConstructor
@RequestMapping("/swstcycleapply")
@Api(value = "swstcycleapply", tags = "调票申请表管理")
public class SwStCycleApplyController {

    private final SwStCycleApplyService swStCycleApplyService;
    private final SwStCycleService swStCycleService;
    private final SupportService supportService;
    private final SystemUserService systemUserService;

    @Resource(name = "invoiceSequence")
    private Sequence invoiceSequence;

    /**
     * 分页查询
     *
     * @param page           分页对象
     * @param swStCycleApply 调票申请表
     * @return
     */
    @ApiOperation(value = "分页查询", notes = "分页查询")
    @GetMapping("/page")
    public R getPage(Page page, SwStCycleApply swStCycleApply) {
        //申请时间
        List<String> dateCondition = swStCycleApply.getDates1();
        LambdaQueryWrapper<SwStCycleApply> queryWrapper = Wrappers.<SwStCycleApply>query(swStCycleApply).orderByDesc("apply_time").orderByDesc("create_time").lambda();

        if (ObjectUtil.isNotEmpty(dateCondition)) {
            queryWrapper.apply("DATE_FORMAT(apply_time,'%Y-%m-%d') between DATE_FORMAT('"+dateCondition.get(0)+"','%Y-%m-%d') and DATE_FORMAT('"+dateCondition.get(1)+"','%Y-%m-%d')");
        }

        if (SecurityUtils.getUser().getBelongToLine()) {
            queryWrapper.ne(SwStCycleApply::getReviewStatus, CycleEnum.REVIEW_STATUS_NONE.getCode());
        } else {
            queryWrapper.eq(SwStCycleApply::getApplyStation, SecurityUtils.getUser().getStationCode());
        }

        return R.ok(swStCycleApplyService.page(page, queryWrapper));
    }


    /**
     * 通过id查询调票申请表
     *
     * @param id id
     * @return R
     */
    @ApiOperation(value = "通过id查询", notes = "通过id查询")
    @GetMapping("/{id}")
    public R getById(@PathVariable("id") Integer id) {
        return R.ok(swStCycleApplyService.getById(id));
    }

    /**
     * 新增调票申请表
     *
     * @param swStCycleApply 调票申请表
     * @return R
     */
    @ApiOperation(value = "新增调票申请表", notes = "新增调票申请表")
    @SysLog("新增调票申请表")
    @PostMapping
    @PreAuthorize("@pms.hasPermission('stm_swstcycleapply_add')")
    public R save(@RequestBody SwStCycleApply swStCycleApply) {
        //未完成
        swStCycleApply.setHandleStatus("0");
        //未提交
        swStCycleApply.setReviewStatus("0");
        swStCycleApply.setApplyLine(SecurityUtils.getUser().getLineCode());
        swStCycleApply.setApplyStation(SecurityUtils.getUser().getStationCode());
        return R.ok(swStCycleApplyService.save(swStCycleApply));
    }

    /**
     * 修改调票申请表
     *
     * @param swStCycleApply 调票申请表
     * @return R
     */
    @ApiOperation(value = "修改调票申请表", notes = "修改调票申请表")
    @SysLog("修改调票申请表")
    @PutMapping
    @PreAuthorize("@pms.hasPermission('stm_swstcycleapply_edit')")
    public R updateById(@RequestBody SwStCycleApply swStCycleApply) {
//        SwStCycleApply before = swStCycleApplyService.getById(swStCycleApply.getId());
//        if (swStCycleApplyService.updateById(swStCycleApply)) {
//            Map<String, Map> fileds = CompareFileds
//                    .compareFields(before, swStCycleApply, CompareFileds.getFileds(swStCycleApply));
//            List<SwStOperateLogDTO> list = LogHandler.setLogParms(fileds, before);
//            return R.ok(supportService.logSaveBatch(list, SecurityConstants.FROM_IN));
//        } else {
//            return R.failed("修改调票申请失败");
//        }
        return R.ok(swStCycleApplyService.updateById(swStCycleApply));
    }

    /**
     * 通过id删除调票申请表
     *
     * @param id id
     * @return R
     */
    @ApiOperation(value = "通过id删除调票申请表", notes = "通过id删除调票申请表")
    @SysLog("通过id删除调票申请表")
    @DeleteMapping("/{id}")
    @PreAuthorize("@pms.hasPermission('stm_swstcycleapply_del')")
    public R removeById(@PathVariable Integer id) {
        SwStCycleApply before = swStCycleApplyService.getById(id);
        swStCycleApplyService.removeById(id);
        SwStOperateLogDTO swStOperateLogDTO = LogHandler.setDelLog(before);
        return R.ok(supportService.logSave(swStOperateLogDTO));
    }
    /**
     * 批量删除
     * @param idList
     * @return
     */
    @SysLog("通过id批量删除调票申请")
    @DeleteMapping("/delBatchObj")
    @Transactional
    @ApiOperation(value = "通过id批量删除调票申请", notes = "通过id批量删除调票申请")
	@PreAuthorize("@pms.hasPermission('stm_swstcycleapply_del')")
    public R batchRemoveById(@RequestBody List<Integer> idList) {
        /*
		List<SwStCycleApply> list = swStCycleApplyService.list(new QueryWrapper<SwStCycleApply>().lambda().in(SwStCycleApply::getId, idList));
       
		List<Integer> deleteIds = list.stream().filter(x -> !x.getReviewStatus().equals(CommonConstants.SUBMIT)).map(x -> x.getId()).collect(Collectors.toList());
        if(CollectionUtil.isEmpty(deleteIds)){
            return R.failed(StmConstans.failedDelete);
        }
		  deleteIds.forEach(swStCycleApplyService::removeById);
		*/
		  idList.forEach(swStCycleApplyService::removeById);
      
        return R.ok();
    }

    /**
     * 审核申请
     * 审核通过直接操作调票记录表
     *
     * @param list 审核申请
     * @return R
     */
    @ApiOperation(value = "审核申请", notes = "审核申请")
    @SysLog("审核申请")
    @PutMapping("/auditBatch")
    @PreAuthorize("@pms.hasPermission('stm_swstcycleapply_audit')")
    public R auditById(@RequestBody List<SwStCycleApply> list) {
        ArrayList<SwStCycleApply> swStCycleApplies = new ArrayList<>();
        //TODO 审批的时候直接操作调票记录表
        list.forEach(stCycleApply -> {
            if (stCycleApply.getReviewStatus().equals(CycleEnum.REVIEW_STATUS_SUC.getCode())) {
                SwStCycle swStCycle = new SwStCycle();
                swStCycle.setOrderNum(invoiceSequence.nextNo());
                swStCycle.setApplyId(stCycleApply.getId());
                swStCycle.setCardType(stCycleApply.getTicketType());
                swStCycle.setMoney(stCycleApply.getTicketMoney());
                /**
                 * 次数和金额两者选其一
                 */
                if (null != stCycleApply.getTicketNumber()) {
                    swStCycle.setAmount(stCycleApply.getTicketNumber());
                }
                if (null != stCycleApply.getTicketMoney()) {
                    swStCycle.setMoney(stCycleApply.getTicketMoney());
                }
                swStCycle.setInLineCode(stCycleApply.getApplyLine());
                swStCycle.setInStationCode(stCycleApply.getApplyStation());
                swStCycle.setOutNumber(stCycleApply.getCycleNumber());
                swStCycle.setMakePerson(SecurityUtils.getUser().getNikeName());
                swStCycle.setMakePersonCode(SecurityUtils.getUser().getUserCode());
                swStCycle.setCardTypeParam(stCycleApply.getTicketTypeParam());
                swStCycleService.save(swStCycle);
                SwStCycleApply upSwStCycleApply = new SwStCycleApply();
                upSwStCycleApply.setCycleId(swStCycle.getId());
                upSwStCycleApply.setId(stCycleApply.getId());
                /**
                 * 将状态置为审核通过
                 */
                upSwStCycleApply.setReviewStatus(stCycleApply.getReviewStatus());
                swStCycleApplies.add(upSwStCycleApply);
            } else {
                SwStCycleApply upSwStCycleApply = new SwStCycleApply();
                upSwStCycleApply.setId(stCycleApply.getId());
                /**
                 * 将状态置为审核未通过
                 */
                upSwStCycleApply.setReviewStatus(CycleEnum.REVIEW_STATUS__FAIL.getCode());
                swStCycleApplies.add(upSwStCycleApply);
            }
        });

        return R.ok(swStCycleApplyService.updateBatchById(swStCycleApplies));
    }

    /**
     * 提交申请
     * 此处前端应控制只把状态为未提交的传过来
     *
     * @param list 提交申请
     * @return R
     */
    @ApiOperation(value = "提交申请", notes = "提交申请")
    @SysLog("提交申请")
    @PutMapping("/submitBatch")
    @PreAuthorize("@pms.hasPermission('stm_swstcycleapply_submit')")
    public R submitById(@RequestBody List<SwStCycleApply> list) {
        //正常调票流程（线网需审批及通知）
        /*for (SwStCycleApply swStCycleApply : list) {
            swStCycleApply.setReviewStatus(CycleEnum.REVIEW_STATUS_STAY.getCode());
        }
        return R.ok(swStCycleApplyService.updateBatchById(list));*/
        //车站提交无需线网审批（模拟线网审批及通知流程---自动审批并通知）
        ArrayList<SwStCycleApply> swStCycleApplies = new ArrayList<>();
        //TODO 审批的时候直接操作调票记录表
        list.forEach(stCycleApply -> {
            SwStCycle swStCycle = new SwStCycle();
            swStCycle.setOrderNum(invoiceSequence.nextNo());
            swStCycle.setApplyId(stCycleApply.getId());
            swStCycle.setCardType(stCycleApply.getTicketType());
            swStCycle.setMoney(stCycleApply.getTicketMoney());
            /**
             * 次数和金额两者选其一
             */
            if (null != stCycleApply.getTicketNumber()) {
                swStCycle.setAmount(stCycleApply.getTicketNumber());
            }
            if (null != stCycleApply.getTicketMoney()) {
                swStCycle.setMoney(stCycleApply.getTicketMoney());
            }
            swStCycle.setInLineCode(stCycleApply.getApplyLine());
            swStCycle.setInStationCode(stCycleApply.getApplyStation());
            swStCycle.setOutLineCode(stCycleApply.getOutLineCode());
            swStCycle.setOutStationCode(stCycleApply.getOutStationCode());
            swStCycle.setOutNumber(stCycleApply.getCycleNumber());
            swStCycle.setMakePerson(SecurityUtils.getUser().getNikeName());
            swStCycle.setMakePersonCode(SecurityUtils.getUser().getUserCode());
            swStCycle.setCardTypeParam(stCycleApply.getTicketTypeParam());
            swStCycle.setNoticeStatus(CycleEnum.CONFIRM_SUC.getCode());
            swStCycle.setCycleCase(stCycleApply.getCycleCase());
            //避免重复提交的问题 20240808
			SwStCycle cycleRepeat = new SwStCycle();
			cycleRepeat.setApplyId(stCycleApply.getId());			
			List<SwStCycle> swStCycleList =  swStCycleService.list(Wrappers.query(cycleRepeat));			
			if(swStCycleList!=null && swStCycleList.size()>0){
				  swStCycle.setId(swStCycleList.get(0).getId());
				  swStCycleService.updateById(swStCycle);
			}else{
				 swStCycleService.save(swStCycle);
			}		
           
            SwStCycleApply upSwStCycleApply = new SwStCycleApply();
            upSwStCycleApply.setCycleId(swStCycle.getId());
            upSwStCycleApply.setId(stCycleApply.getId());

			

            /**
             * 将状态置为审核通过
             */
            upSwStCycleApply.setReviewStatus(CycleEnum.REVIEW_STATUS_STAY.getCode());
            swStCycleApplies.add(upSwStCycleApply);
        });
        return R.ok(swStCycleApplyService.updateBatchById(swStCycleApplies));
    }


    /**
     * 定时任务改变办理状态
     * 调出超过三天的自动完成，填充调入数据
     *
     * @return R
     */
    @ApiOperation(value = "定时任务改变办理状态", notes = "定时任务改变办理状态")
    @SysLog("定时任务改变办理状态")
    @PutMapping("/task/changeHandle")
    @Inner
    public R timer() {
        List<SwStCycleApply> list = swStCycleApplyService.getOverTimer();
        ArrayList<Integer> integers = new ArrayList<>();
        list.forEach(swStCycleApply -> {
            swStCycleApply.setHandleStatus(CycleEnum.APPLY_HANDLE_STATUS_SUC.getCode());
            integers.add(swStCycleApply.getCycleId());
        });
        /**
         * 更新申请表办理状态
         */
        swStCycleApplyService.updateBatchById(list);
        /**
         * 更新调票记录表办理状态
         */
        Collection<SwStCycle> swStCycles = swStCycleService.listByIds(integers);
        /**
         * 查询线网直接添加的调票记录，因为上面的处理是从调票申请过来的，数据不全。
         */
        List<SwStCycle> overTime = swStCycleService.getOverTime();
        /**
         * 合并两个集合
         */
        swStCycles.addAll(overTime);
        swStCycles.forEach(swStCycle -> {
            swStCycle.setHandleStatus(CycleEnum.HANDLE_STATUS_COMPLETE.getCode());
            swStCycle.setIsConfirmIn(CycleEnum.CONFIRM_SUC.getCode());
            swStCycle.setInNumber(swStCycle.getOutNumber());
            swStCycle.setInTime(LocalDateTime.now());
        });


        /**
         * 更新接收数量   默认值
         */
        return R.ok(swStCycleService.updateBatchById(swStCycles));
    }

    /**
     * 分页查询
     *
     * @param page           分页对象
     * @param swStCycleApply 调票申请表
     * @return
     */
    @ApiOperation(value = "分页关联查询", notes = "分页关联查询")
    @GetMapping("/pageMapper")
    public R getSwStCycleApplyPage(Page page, SwStCycleApply swStCycleApply) {

        String s = invoiceSequence.nextNo();

        UserInfo info = systemUserService.info().getData();
        if (info.getSysUser().getBelongToLine() == true) {
            return R.ok(swStCycleApplyService.pageMapper(page,
                    Wrappers.query(swStCycleApply)
                            .allEq(SelMapUtils.getSwStCycleApplyMap(swStCycleApply), false)));
        } else {
            return R.ok(swStCycleApplyService.pageMapper(page,
                    Wrappers.query(swStCycleApply)
                            .allEq(SelMapUtils.getSwStCycleApplyMap(swStCycleApply), false)
                            .eq("a.APPLY_STATION", info.getSysUser().getStationCode())
            ));
        }

    }

    /**
     * 导出车票上交信息
     *
     * @param swStCycleApply
     * @param response
     * @throws IOException
     */
    @ApiOperation(value = "导出调票申请", notes = "导出调票申请")
    @GetMapping("/export")
    @SysLog("导出调票申请")
    public void exportExcel(SwStCycleApply swStCycleApply, HttpServletResponse response) throws IOException {

        LambdaQueryWrapper<SwStCycleApply> queryWrapper = Wrappers.<SwStCycleApply>query(swStCycleApply).lambda();

        if (SecurityUtils.getUser().getBelongToLine()) {
            queryWrapper.ne(SwStCycleApply::getReviewStatus, CycleEnum.REVIEW_STATUS_NONE.getCode());
        } else {
            queryWrapper.eq(SwStCycleApply::getApplyStation, SecurityUtils.getUser().getStationCode());
        }

        List<SwStCycleApply> swStCycleApplyList = swStCycleApplyService.list(queryWrapper);
        String fileName = URLEncoder.encode("调票申请", "UTF-8");
        response.setHeader("Content-disposition", "attachment;filename=" + fileName + System.currentTimeMillis() + ".xlsx");
        EasyExcel.write(response.getOutputStream(), SwStCycleApply.class).registerConverter(new LocalDateTimeConverter())
                .registerConverter(new LocalDateConverter()).sheet("调票申请").doWrite(swStCycleApplyList);
    }
}
